package com.stationpc.dock.service

import android.app.*
import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import android.content.IntentFilter
import android.content.pm.PackageManager
import android.graphics.PixelFormat
import android.net.Uri
import android.os.IBinder
import android.provider.Settings
import android.util.Log
import android.view.Gravity
import android.view.KeyEvent
import android.view.LayoutInflater
import android.view.View
import android.view.WindowManager
import android.widget.FrameLayout
import android.widget.GridLayout
import android.widget.ImageView
import android.widget.Toast
import androidx.core.app.NotificationCompat
import com.stationpc.dock.R
import android.os.Build

class DockOverlayService : Service() {

    private lateinit var windowManager: WindowManager
    private lateinit var overlayView: View
    private lateinit var gridLayout: GridLayout
    private var isOverlayShown = false
    private var currentFocusIndex = 0
    private var selectedAppsCache: Set<String> = emptySet()

    companion object {
        private const val NOTIFICATION_ID = 1
        private const val CHANNEL_ID = "DockOverlayServiceChannel"
        const val ACTION_TOGGLE_VISIBILITY = "com.stationpc.dock.TOGGLE_VISIBILITY"
    }

    override fun onCreate() {
        super.onCreate()
        windowManager = getSystemService(Context.WINDOW_SERVICE) as WindowManager
        createOverlayView()
        createNotificationChannel()
        startForeground(NOTIFICATION_ID, createNotification())
    }

    override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
        when (intent?.action) {
            ACTION_TOGGLE_VISIBILITY -> toggleOverlayVisibility()
        }
        return START_STICKY
    }

    private fun createOverlayView() {
        overlayView = LayoutInflater.from(this).inflate(R.layout.overlay_dock, null)
        gridLayout = overlayView.findViewById(R.id.dockGridLayout)

        val params = WindowManager.LayoutParams(
            WindowManager.LayoutParams.WRAP_CONTENT,
            WindowManager.LayoutParams.WRAP_CONTENT,
            WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY,
            WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL or
                    WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN,
            PixelFormat.TRANSLUCENT
        )
        params.gravity = Gravity.BOTTOM or Gravity.CENTER_HORIZONTAL

        loadSelectedApps(gridLayout)

        overlayView.isFocusable = true
        overlayView.isFocusableInTouchMode = true

        overlayView.setOnKeyListener { _, keyCode, event ->
            if (event.action == KeyEvent.ACTION_DOWN) {
                when (keyCode) {
                    KeyEvent.KEYCODE_DPAD_LEFT -> moveFocus(-1)
                    KeyEvent.KEYCODE_DPAD_RIGHT -> moveFocus(1)
                    KeyEvent.KEYCODE_DPAD_CENTER, KeyEvent.KEYCODE_ENTER -> launchFocusedApp()
                    KeyEvent.KEYCODE_PAGE_DOWN -> {
                        toggleOverlayVisibility()
                        return@setOnKeyListener true
                    }
                    KeyEvent.KEYCODE_BACK -> {
                        if (isOverlayShown) {
                            toggleOverlayVisibility()
                            return@setOnKeyListener true
                        }
                    }
                    else -> return@setOnKeyListener false
                }
                return@setOnKeyListener true
            }
            false
        }

        windowManager.addView(overlayView, params)
        overlayView.visibility = View.GONE
        isOverlayShown = false
    }

    private fun loadSelectedApps(gridLayout: GridLayout) {
        val sharedPrefs = getSharedPreferences("DockPrefs", Context.MODE_PRIVATE)
        val selectedPackages = sharedPrefs.getStringSet("selectedApps", setOf()) ?: setOf()

        if (selectedAppsCache == selectedPackages) return
        selectedAppsCache = selectedPackages
        gridLayout.removeAllViews()

        for (packageName in selectedPackages) {
            try {
                val appInfo = packageManager.getApplicationInfo(packageName, 0)
                val appIconView = LayoutInflater.from(this).inflate(R.layout.dock_app_item, gridLayout, false) as FrameLayout
                val iconView = appIconView.findViewById<ImageView>(R.id.appIcon)

                iconView.setImageDrawable(packageManager.getApplicationIcon(appInfo))

                appIconView.setOnClickListener {
                    launchApp(packageName)
                }

                appIconView.isFocusable = true
                appIconView.isFocusableInTouchMode = true

                appIconView.setOnFocusChangeListener { view, hasFocus ->
                    if (hasFocus) {
                        view.scaleX = 1.25f
                        view.scaleY = 1.25f
                    } else {
                        view.scaleX = 1.0f
                        view.scaleY = 1.0f
                    }
                }

                gridLayout.addView(appIconView)
            } catch (e: PackageManager.NameNotFoundException) {
                Log.e("DockOverlayService", "App not found: $packageName", e)
            }
        }

        if (gridLayout.childCount > 0) {
            currentFocusIndex = 0
            gridLayout.getChildAt(currentFocusIndex).requestFocus()
        }
    }

    private fun moveFocus(direction: Int) {
        val childCount = gridLayout.childCount
        if (childCount == 0) return
        gridLayout.getChildAt(currentFocusIndex).clearFocus()
        currentFocusIndex = (currentFocusIndex + direction + childCount) % childCount
        gridLayout.getChildAt(currentFocusIndex).requestFocus()
    }

    private fun launchFocusedApp() {
        val focusedView = gridLayout.getChildAt(currentFocusIndex)
        focusedView.performClick()
    }

    private fun toggleOverlayVisibility() {
        if (isOverlayShown) {
            hideDock()
        } else {
            overlayView.visibility = View.VISIBLE
            loadSelectedApps(gridLayout)
            if (gridLayout.childCount > 0) {
                currentFocusIndex = 0
                gridLayout.getChildAt(currentFocusIndex).requestFocus()
            }
            isOverlayShown = true
        }
    }

    private fun hideDock() {
        overlayView.visibility = View.GONE
        isOverlayShown = false
    }

    private fun launchApp(packageName: String) {
        val launchIntent = packageManager.getLaunchIntentForPackage(packageName)
        if (launchIntent != null) {
            launchIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
            startActivity(launchIntent)
        } else {
            Log.e("DockOverlayService", "Unable to launch app: $packageName")
            Toast.makeText(this, "App not found: $packageName", Toast.LENGTH_SHORT).show()
        }
    }

    private fun minimizeBackgroundApp() {
        val homeIntent = Intent(Intent.ACTION_MAIN)
        homeIntent.addCategory(Intent.CATEGORY_HOME)
        homeIntent.flags = Intent.FLAG_ACTIVITY_NEW_TASK
        startActivity(homeIntent)
    }

    private fun createNotificationChannel() {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            val name = getString(R.string.channel_name)
            val descriptionText = getString(R.string.channel_description)
            val importance = NotificationManager.IMPORTANCE_LOW
            val channel = NotificationChannel(CHANNEL_ID, name, importance).apply {
                description = descriptionText
            }
            val notificationManager: NotificationManager =
                getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
            notificationManager.createNotificationChannel(channel)
        }
    }

    private fun createNotification(): Notification {
        return NotificationCompat.Builder(this, CHANNEL_ID)
            .setContentTitle(getString(R.string.app_name))
            .setContentText(getString(R.string.notification_text))
            .setSmallIcon(R.drawable.ic_launcher2)
            .setPriority(NotificationCompat.PRIORITY_LOW)
            .build()
    }

    override fun onBind(intent: Intent): IBinder? {
        return null
    }

    override fun onDestroy() {
        super.onDestroy()
        if (::overlayView.isInitialized && overlayView.isAttachedToWindow) {
            windowManager.removeView(overlayView)
        }
    }
}
